package com.csu.cphone.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import com.csu.common.exception.WebException;
import com.csu.common.sms.SMSSender;
import com.csu.common.utils.HttpUtil;
import com.csu.common.utils.JsonUtil;
import com.csu.common.utils.RedisUtil;
import com.csu.common.utils.UUIDUtil;
import com.csu.cphone.constants.ErrorCode;
import com.csu.cphone.constants.RedisKey;
import com.csu.cphone.dao.MaintainOrderMapper;
import com.csu.cphone.dao.MaintainProblemSelectMapper;
import com.csu.cphone.dao.MaintainSelectAnswerMapper;
import com.csu.cphone.dao.ProducerMapper;
import com.csu.cphone.pojo.MaintainOrderPojo;
import com.csu.cphone.pojo.MaintainProblemPojo;
import com.csu.cphone.pojo.MaintainProblemSelectPojo;
import com.csu.cphone.pojo.MaintainSelectAnswerPojo;
import com.csu.cphone.pojo.ProducerPojo;
import com.csu.cphone.pojo.StorePojo;
import com.csu.cphone.service.MaintainOrderService;
import com.csu.cphone.service.MaintainService;
import com.csu.cphone.service.StoreService;
import com.csu.cphone.vo.MaintainOrderVo;
import com.csu.cphone.vo.OrderCacheInfo;
import com.csu.cphone.vo.PayStatusResultVo;

/**
 * @项目名称：cphone
 * @类名称：MaintainOrderServiceImpl
 * @类描述：
 * @创建人：Tangc
 * @创建时间：2017年11月20日 下午4:03:06
 * @company:
 */
@Service
public class MaintainOrderServiceImpl implements MaintainOrderService
{

    @Autowired
    private MaintainOrderMapper maintainOrderMapper;

    @Autowired
    private MaintainService maintainService;

    @Autowired
    private StoreService storeService;

    @Autowired
    private MaintainSelectAnswerMapper maintainSelectAnswerMapper;

    @Autowired
    private MaintainProblemSelectMapper maintainProblemSelectMapper;

    @Autowired
    private ProducerMapper producerMapper;

    /**
     * @throws WebException
     * @see com.csu.cphone.service.MaintainOrderService#commitOrder(com.csu.cphone.vo.MaintainOrderVo)
     */
    @Override
    public MaintainOrderPojo commitOrder(MaintainOrderVo orderVo) throws WebException
    {
        String position = orderVo.getPositon();
        checkPosition(position);

        List<MaintainProblemSelectPojo> problemSelects = orderVo.getProblemSelects();
        Double amount = maintainService.offer(problemSelects);
        String sn = UUIDUtil.getUUID();

        MaintainOrderPojo orderPojo = new MaintainOrderPojo();
        orderPojo.setApplyTime(new Date());
        Integer customerId = orderVo.getCustomerId();
        orderPojo.setCustomerId(customerId);
        Integer serviceType = orderVo.getServiceType();
        orderPojo.setServiceType(serviceType);
        orderPojo.setAmount(amount);
        orderPojo.setRemark(orderVo.getRemark());
        orderPojo.setSerialNumber(sn);
        Integer maintainPhoneId = orderVo.getMaintainPhoneId();
        orderPojo.setMaintainPhoneId(maintainPhoneId);

        if (serviceType == 1)
        {
            orderPojo.setStatus(0);
            orderPojo.setAddress(orderVo.getAddress());
            orderPojo.setPeriod(orderVo.getPeriod());
            OrderCacheInfo map = new OrderCacheInfo();
            map.setSn(sn);
            map.setPosition(position);
            RedisUtil.getRedisDb().lpush(RedisKey.WAITING_ORDER_QUEUE + "maintain", JsonUtil.toJSONString(map));
        }
        else if (serviceType == 2)
        {
            orderPojo.setStatus(1);
            Integer storeId = orderVo.getStoreId();
            orderPojo.setStoreId(storeId);
            StorePojo store = storeService.queryById(storeId);
            Integer producerId = store.getProducerId();
            orderPojo.setProducerId(producerId);
            ProducerPojo producer = producerMapper.selectById(producerId);
            String number = producer.getNumber();
            RedisUtil.getRedisDb().lpush(RedisKey.WAITING_MAINTAIM_ORDER + number, sn);
        }
        else if (serviceType == 3)
        {
            orderPojo.setStatus(2);
            orderPojo.setProducerId(-1);
            orderPojo.setExpressCompany(orderVo.getExpressCompany());
            orderPojo.setExpressNumber(orderVo.getExpressNumber());
            orderPojo.setIphonePasswd(orderVo.getIphonePasswd());
        }
        else
        {
            throw new WebException(ErrorCode.SERVICE_TYPE_ERROR_CODE, ErrorCode.SERVICE_TYPE_ERROR_MEASSAGE);
        }
        insert(sn, maintainPhoneId, problemSelects, orderPojo);
        RedisUtil.getRedisDb().hset(RedisKey.ORDER_POSITION, sn, position);
        return orderPojo;
    }

    /**
     * @description
     * @author TangC
     * @date 2017年12月16日 上午10:47:32
     * @param position
     * @throws WebException
     */
    private void checkPosition(String position) throws WebException
    {
        String[] positions = position.split(",");
        String latString = positions[0];
        String lngString = positions[1];
        if (StringUtils.isEmpty(lngString) || StringUtils.isEmpty(latString))
        {
            throw new WebException(ErrorCode.OrderPositionError, ErrorCode.OrderPositionMessgae);
        }
    }

    /**
     * @description
     * @author TangC
     * @date 2017年11月23日 下午5:21:29
     * @param sn
     * @param maintainPhoneId
     * @param problemSelects
     * @param orderPojo
     */
    private void insert(String sn, Integer maintainPhoneId, List<MaintainProblemSelectPojo> problemSelects,
            MaintainOrderPojo orderPojo)
    {
        if (!CollectionUtils.isEmpty(problemSelects))
        {
            insertAnswer(problemSelects, sn, maintainPhoneId);
        }
        maintainOrderMapper.insert(orderPojo);
    }

    private int insertAnswer(List<MaintainProblemSelectPojo> selects, String sn, Integer maintainPhoneId)
    {
        List<MaintainSelectAnswerPojo> answerPojos = new ArrayList<MaintainSelectAnswerPojo>();

        for (MaintainProblemSelectPojo select : selects)
        {
            MaintainSelectAnswerPojo answerPojo = new MaintainSelectAnswerPojo();
            answerPojo.setMaintainOrderSn(sn);
            answerPojo.setMaintainPhoneId(maintainPhoneId);
            answerPojo.setMaintainProblemId(select.getProblemId());
            answerPojo.setMaintainProblemSelectId(select.getId());
            answerPojo.setCost(select.getCost());
            answerPojos.add(answerPojo);
        }

        return maintainSelectAnswerMapper.batchInsert(answerPojos);
    }

    /**
     * @see com.csu.cphone.service.MaintainOrderService#updateOrder(com.csu.cphone.pojo.MaintainOrderPojo)
     */
    @Override
    public MaintainOrderPojo updateOrder(MaintainOrderPojo orderPojo)
    {

        List<MaintainProblemSelectPojo> problemSelects = orderPojo.getProblemSelects();
        Double amount = maintainService.offer(problemSelects);
        orderPojo.setAmount(amount);
        orderPojo.setAcceptTime(new Date());
        orderPojo.setStatus(2);
        update(orderPojo.getSerialNumber(), orderPojo.getMaintainPhoneId(), problemSelects, orderPojo);

        return orderPojo;
    }

    /**
     * @description
     * @author TangC
     * @date 2017年11月24日 上午10:12:38
     * @param sn
     * @param maintainPhoneId
     * @param problemSelects
     * @param orderPojo
     */

    private void update(String sn, Integer maintainPhoneId, List<MaintainProblemSelectPojo> problemSelects,
            MaintainOrderPojo orderPojo)
    {
        updateAnswer(problemSelects, sn, maintainPhoneId);
        maintainOrderMapper.update(orderPojo);

    }

    /**
     * @description
     * @author TangC
     * @date 2017年11月24日 上午10:16:06
     * @param problemSelects
     * @param sn
     * @param maintainPhoneId
     */

    private Integer updateAnswer(List<MaintainProblemSelectPojo> problemSelects, String sn, Integer maintainPhoneId)
    {
        List<MaintainSelectAnswerPojo> newAnswerPojos = new ArrayList<MaintainSelectAnswerPojo>();
        Map<Integer, MaintainSelectAnswerPojo> newAnswerMap = new HashMap<Integer, MaintainSelectAnswerPojo>();
        Map<Integer, MaintainSelectAnswerPojo> oldAnswerMap = new HashMap<Integer, MaintainSelectAnswerPojo>();
        for (MaintainProblemSelectPojo select : problemSelects)
        {
            MaintainSelectAnswerPojo answerPojo = new MaintainSelectAnswerPojo();
            answerPojo.setMaintainOrderSn(sn);
            answerPojo.setMaintainPhoneId(maintainPhoneId);
            answerPojo.setMaintainProblemId(select.getProblemId());
            Integer selectId1 = select.getId();
            answerPojo.setMaintainProblemSelectId(selectId1);
            answerPojo.setCost(select.getCost());
            newAnswerPojos.add(answerPojo);
            newAnswerMap.put(selectId1, answerPojo);
        }

        List<MaintainSelectAnswerPojo> oldAnswerPojos = maintainSelectAnswerMapper.selectByOrderSn(sn);

        List<Integer> delIds = new ArrayList<Integer>();
        List<MaintainSelectAnswerPojo> addAnswers = new ArrayList<MaintainSelectAnswerPojo>();
        Set<Integer> modifyIds = new HashSet<Integer>();
        for (MaintainSelectAnswerPojo oldAnswerPojo : oldAnswerPojos)
        {
            Integer selectId2 = oldAnswerPojo.getMaintainProblemSelectId();
            oldAnswerMap.put(selectId2, oldAnswerPojo);

            if (newAnswerMap.containsKey(selectId2))
            {
                continue;
            }
            Integer delId = oldAnswerPojo.getId();
            delIds.add(delId);
            modifyIds.add(selectId2);
        }

        for (MaintainSelectAnswerPojo newAnswerPojo : oldAnswerPojos)
        {
            Integer selectId3 = newAnswerPojo.getMaintainProblemSelectId();
            if (oldAnswerMap.containsKey(selectId3))
            {
                continue;
            }
            addAnswers.add(newAnswerPojo);
            modifyIds.add(selectId3);
        }
        if (!CollectionUtils.isEmpty(delIds))
        {
            maintainSelectAnswerMapper.batchDel(delIds);
        }
        if (!CollectionUtils.isEmpty(addAnswers))
        {
            maintainSelectAnswerMapper.batchInsert(addAnswers);
        }

        return modifyIds.size();

    }

    /**
     * @see com.csu.cphone.service.MaintainOrderService#getOrderBySn(java.lang.String)
     */
    @Override
    public MaintainOrderPojo getOrderBySn(String serialNumber)
    {
        MaintainOrderPojo maintainOrder = maintainOrderMapper.selectBySn(serialNumber);
        List<MaintainProblemSelectPojo> problemSelects = getProblemSelects(maintainOrder.getSerialNumber());
        maintainOrder.setProblemSelects(problemSelects);
        List<MaintainProblemPojo> problems = maintainService.getMaintainProblemsByPhoneId(maintainOrder
                .getMaintainPhoneId());
        maintainOrder.setProblems(problems);
        updatePayStatus(maintainOrder, serialNumber);
        return maintainOrder;
    }

    /**
     * @see com.csu.cphone.service.MaintainOrderService#queryOrdersByCustomerId(int)
     */
    @Override
    public List<MaintainOrderPojo> queryOrdersByCustomerId(int customerId)
    {
        List<MaintainOrderPojo> maintainOrders = maintainOrderMapper.selectByCustomerId(customerId);
        if (maintainOrders != null)
        {
            for (MaintainOrderPojo maintainOrder : maintainOrders)
            {
                List<MaintainProblemSelectPojo> problemSelects = getProblemSelects(maintainOrder.getSerialNumber());
                maintainOrder.setProblemSelects(problemSelects);
                List<MaintainProblemPojo> problems = maintainService.getMaintainProblemsByPhoneId(maintainOrder
                        .getMaintainPhoneId());
                maintainOrder.setProblems(problems);
                updatePayStatus(maintainOrder, maintainOrder.getSerialNumber());
            }
        }

        return maintainOrders;
    }

    /**
     * @see com.csu.cphone.service.MaintainOrderService#queryById(java.lang.Integer)
     */
    @Override
    public MaintainOrderPojo queryById(Integer maintainOrderId)
    {
        MaintainOrderPojo maintainOrder = maintainOrderMapper.selectById(maintainOrderId);
        String serialNumber = maintainOrder.getSerialNumber();
        List<MaintainProblemSelectPojo> problemSelects = getProblemSelects(serialNumber);
        maintainOrder.setProblemSelects(problemSelects);
        List<MaintainProblemPojo> problems = maintainService.getMaintainProblemsByPhoneId(maintainOrder
                .getMaintainPhoneId());
        maintainOrder.setProblems(problems);
        updatePayStatus(maintainOrder, serialNumber);
        return maintainOrder;
    }

    /**
     * @description
     * @author TangC
     * @date 2017年12月17日 下午10:15:03
     * @param maintainOrder
     * @param serialNumber
     */

    private void updatePayStatus(MaintainOrderPojo maintainOrder, String serialNumber)
    {
        if (maintainOrder.getPayStatus() == 0)
        {
            int status = getPayStatusBysn(serialNumber);
            if (status == 1)
            {
                maintainOrder.setPayStatus(status);
                Map<String, Object> map = new HashMap<String, Object>();
                map.put("serialNumber", serialNumber);
                map.put("payStatus", status);
                maintainOrderMapper.updatePayStatus(map);
            }
        }
    }

    /**
     * @description
     * @author TangC
     * @date 2017年12月16日 下午10:00:11
     * @param serialNumber
     * @return
     */
    private List<MaintainProblemSelectPojo> getProblemSelects(String serialNumber)
    {
        List<MaintainSelectAnswerPojo> maintainSelectAnswers = maintainSelectAnswerMapper.selectByOrderSn(serialNumber);
        List<Integer> selectIds = new ArrayList<Integer>();
        List<MaintainProblemSelectPojo> problemSelects = new ArrayList<MaintainProblemSelectPojo>();
        if (!CollectionUtils.isEmpty(maintainSelectAnswers))
        {
            for (MaintainSelectAnswerPojo maintainSelectAnswer : maintainSelectAnswers)
            {
                Integer selectId = maintainSelectAnswer.getMaintainProblemSelectId();
                selectIds.add(selectId);
            }
            problemSelects = maintainProblemSelectMapper.selectByIds(selectIds);
        }

        return problemSelects;
    }

    /**
     * @see com.csu.cphone.service.MaintainOrderService#count()
     */
    @Override
    public Integer count()
    {
        return maintainOrderMapper.count();
    }

    /**
     * @see com.csu.cphone.service.MaintainOrderService#queryList(java.lang.Integer,
     *      java.lang.Integer, java.lang.String)
     */
    @Override
    public List<MaintainOrderPojo> queryList(Integer pageSize, Integer startIndex, String order)
    {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("pageSize", pageSize);
        map.put("startIndex", startIndex);
        map.put("order", order);

        List<MaintainOrderPojo> maintainOrders = maintainOrderMapper.queryList(map);
        if (maintainOrders != null)
        {
            for (MaintainOrderPojo maintainOrder : maintainOrders)
            {
                List<MaintainProblemSelectPojo> problemSelects = getProblemSelects(maintainOrder.getSerialNumber());
                maintainOrder.setProblemSelects(problemSelects);
                List<MaintainProblemPojo> problems = maintainService.getMaintainProblemsByPhoneId(maintainOrder
                        .getMaintainPhoneId());
                maintainOrder.setProblems(problems);
                updatePayStatus(maintainOrder, maintainOrder.getSerialNumber());
            }
        }
        return maintainOrders;
    }

    /**
     * @see com.csu.cphone.service.MaintainOrderService#deleteById(java.lang.Integer)
     */
    @Override
    public Integer deleteById(Integer maintainOrderId)
    {
        return maintainOrderMapper.deleteById(maintainOrderId);
    }

    /**
     * @see com.csu.cphone.service.MaintainOrderService#getWaitingOrder(int)
     */
    @Override
    public List<MaintainOrderPojo> getWaitingOrder(String number)
    {
        RedisUtil.getRedisDb().del(RedisKey.WAITING_MAINTAIM_ORDER + number);
        ProducerPojo producer = producerMapper.selectByNumber(number);
        Integer producerId = producer.getId();
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("producerId", producerId);
        map.put("status", 1);
        List<MaintainOrderPojo> waitingOrders = maintainOrderMapper.getByProducerIdAndStatus(map);
        if (waitingOrders != null)
        {
            for (MaintainOrderPojo maintainOrder : waitingOrders)
            {
                List<MaintainProblemSelectPojo> problemSelects = getProblemSelects(maintainOrder.getSerialNumber());
                maintainOrder.setProblemSelects(problemSelects);
                List<MaintainProblemPojo> problems = maintainService.getMaintainProblemsByPhoneId(maintainOrder
                        .getMaintainPhoneId());
                maintainOrder.setProblems(problems);
                updatePayStatus(maintainOrder, maintainOrder.getSerialNumber());
            }
        }
        return waitingOrders;
    }

    /**
     * @see com.csu.cphone.service.MaintainOrderService#cancelOrder(java.lang.String,
     *      int)
     */
    @Override
    public Integer cancelOrder(String orderSn, int customerId)
    {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("customerId", customerId);
        map.put("cancelTime", new Date());
        map.put("serialNumber", orderSn);
        return maintainOrderMapper.cancelOrder(map);
    }

    private int getPayStatusBysn(String serialNumber)
    {
        String url = "http://www.chuangshouji.com/CPhoneRaffle/WeixinPay/getPayStatus";
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("serialNumber", serialNumber);
        String result = HttpUtil.getMap(url, params);
        PayStatusResultVo statusVo = JsonUtil.toObject(result, PayStatusResultVo.class);
        return statusVo.getStatus();
    }

    /**
     * @see com.csu.cphone.service.MaintainOrderService#finishOrder(java.lang.String)
     */
    @Override
    public Integer finishOrder(String serialNumber)
    {
        MaintainOrderPojo orderPojo = new MaintainOrderPojo();
        orderPojo.setFinishTime(new Date());
        orderPojo.setStatus(3);
        orderPojo.setSerialNumber(serialNumber);
        Integer update = maintainOrderMapper.update(orderPojo);
        if (update != null && update != 0)
        {
            String number = maintainOrderMapper.selectNumberBySn(serialNumber);
            if (number != null)
            {
                SMSSender.sendSMSByType(number, null, 4);
            }
        }
        return update;
    }

    /**
     * @see com.csu.cphone.service.MaintainOrderService#confirmFinish(java.lang.String)
     */
    @Override
    public Integer confirmFinish(String serialNumber)
    {
        MaintainOrderPojo orderPojo = new MaintainOrderPojo();
        orderPojo.setConfirmTime(new Date());
        orderPojo.setStatus(4);
        orderPojo.setSerialNumber(serialNumber);
        return maintainOrderMapper.update(orderPojo);
    }

    /**
     * @see com.csu.cphone.service.MaintainOrderService#queryOrderByProducer(java.lang.String,
     *      java.lang.Integer)
     */
    @Override
    public List<MaintainOrderPojo> queryOrderByProducer(String number, Integer status)
    {
        if (status == null || status == 1)
        {
            RedisUtil.getRedisDb().del(RedisKey.WAITING_MAINTAIM_ORDER + number);
        }
        ProducerPojo producer = producerMapper.selectByNumber(number);
        Integer producerId = producer.getId();
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("producerId", producerId);
        map.put("status", status);
        List<MaintainOrderPojo> orders = maintainOrderMapper.getByProducerIdAndStatus(map);
        if (orders != null)
        {
            for (MaintainOrderPojo maintainOrder : orders)
            {
                List<MaintainProblemSelectPojo> problemSelects = getProblemSelects(maintainOrder.getSerialNumber());
                maintainOrder.setProblemSelects(problemSelects);
                List<MaintainProblemPojo> problems = maintainService.getMaintainProblemsByPhoneId(maintainOrder
                        .getMaintainPhoneId());
                maintainOrder.setProblems(problems);
                updatePayStatus(maintainOrder, maintainOrder.getSerialNumber());
            }
        }
        return orders;
    }

    /**
     * @see com.csu.cphone.service.MaintainOrderService#turnOrder(java.lang.String,
     *      java.lang.String)
     */
    @Override
    public MaintainOrderPojo turnOrder(String sn, String number) throws WebException
    {
        ProducerPojo producer = producerMapper.selectByNumber(number);
        if (producer == null)
        {
            throw new WebException(ErrorCode.UserNullCode, ErrorCode.UserNullMessgae);
        }
        MaintainOrderPojo order = maintainOrderMapper.selectBySn(sn);
        if (order == null)
        {
            throw new WebException(ErrorCode.OrderNullError, ErrorCode.OrderNullMessgae);
        }

        order.setProducerId(producer.getId());
        order.setAcceptTime(new Date());
        maintainOrderMapper.update(order);
        return order;
    }
}
